<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="路由控制、数据加密、数据更新、数据缓存、组件库优化">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue 常见场景的解决方案">
<meta property="og:url" content="https://chuangges.gitee.io/2019/06/10/5-2-vue%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="路由控制、数据加密、数据更新、数据缓存、组件库优化">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://chuangges.gitee.io/images/frame/crypto.png">
<meta property="article:published_time" content="2019-06-10T15:11:50.000Z">
<meta property="article:modified_time" content="2023-05-11T08:54:49.510Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="JS 框架">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://chuangges.gitee.io/images/frame/crypto.png">

<link rel="canonical" href="https://chuangges.gitee.io/2019/06/10/5-2-vue%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Vue 常见场景的解决方案 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/06/10/5-2-vue%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Vue 常见场景的解决方案
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-06-10 23:11:50" itemprop="dateCreated datePublished" datetime="2019-06-10T23:11:50+08:00">2019-06-10</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-05-11 16:54:49" itemprop="dateModified" datetime="2023-05-11T16:54:49+08:00">2023-05-11</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JS-%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">JS 框架</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>16k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>14 分钟</span>
            </span>
            <div class="post-description">路由控制、数据加密、数据更新、数据缓存、组件库优化</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、路由控制"><a href="#一、路由控制" class="headerlink" title="一、路由控制"></a>一、路由控制</h1><blockquote>
<p>Token 是包含用户名、有效期和某些专有信息并通过共享密钥加密的信息字符串。</p>
</blockquote>
<h2 id="登录验证"><a href="#登录验证" class="headerlink" title="登录验证"></a>登录验证</h2><ol>
<li>客户端发送用户名和密码请求登录，服务端收到进行验证。</li>
<li>服务端验证成功后生成唯一的 Token 存储在数据库并返回给客户端。</li>
<li>客户端收到 Token 后通过 Cookie、Vuex 等方式存储。</li>
<li>客户端每次向服务端请求资源时都携带 Token。</li>
<li>服务端收到请求后去验证 Token，验证成功则返回数据。</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前端路由验证</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [&#123;</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">    <span class="attr">component</span>: <span class="built_in">require</span>(<span class="string">&#x27;./views/Home&#x27;</span>),</span><br><span class="line">    <span class="attr">meta</span>: &#123; <span class="attr">requiresAuth</span>: <span class="literal">true</span>  &#125;</span><br><span class="line">  &#125;]</span><br><span class="line">&#125;)</span><br><span class="line">router.<span class="title function_">beforeEach</span>(<span class="function">(<span class="params">to, <span class="keyword">from</span>, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (to.<span class="property">meta</span>.<span class="property">requireAuth</span>) &#123;    </span><br><span class="line">      <span class="keyword">if</span> (store.<span class="property">state</span>.<span class="property">token</span>) &#123;  </span><br><span class="line">          <span class="title function_">next</span>();</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="comment">// 记录目标路由，用于登录成功后直接跳转</span></span><br><span class="line">          <span class="title function_">next</span>(&#123;</span><br><span class="line">            <span class="attr">path</span>: <span class="string">&#x27;/login&#x27;</span>,</span><br><span class="line">            <span class="attr">query</span>: &#123;<span class="attr">redirect</span>: to.<span class="property">fullPath</span>&#125;</span><br><span class="line">          &#125;)</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">      <span class="title function_">next</span>()</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 服务端验证</span></span><br><span class="line">axios.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (store.<span class="property">state</span>.<span class="property">token</span>) &#123;  </span><br><span class="line">        config.<span class="property">headers</span>[<span class="string">&#x27;Token&#x27;</span>] = store.<span class="property">state</span>.<span class="property">token</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> config;</span><br><span class="line">  &#125;)</span><br><span class="line">axios.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (error.<span class="property">res</span>.<span class="property">status</span> == <span class="number">401</span>) &#123;</span><br><span class="line">        <span class="comment">// 清除 token 信息并跳转到登录页面</span></span><br><span class="line">        store.<span class="title function_">commit</span>(<span class="string">&quot;token_clear&quot;</span>);</span><br><span class="line">        router.<span class="title function_">replace</span>(&#123;</span><br><span class="line">          <span class="attr">path</span>: <span class="string">&#x27;login&#x27;</span>,</span><br><span class="line">          <span class="attr">query</span>: &#123;<span class="attr">redirect</span>: router.<span class="property">currentRoute</span>.<span class="property">fullPath</span>&#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error.<span class="property">response</span>.<span class="property">data</span>)   </span><br><span class="line">  &#125;)</span><br></pre></td></tr></table></figure>


<h2 id="权限控制"><a href="#权限控制" class="headerlink" title="权限控制"></a>权限控制</h2><blockquote>
<p>路由表一般由 Vuex 管理。</p>
</blockquote>
<ol>
<li>初始化路由时挂载登录、注册等公共组件。</li>
<li>用户登录后，客户端获取服务器返回的路由数据。</li>
<li>客户端触发 vuex 相关方法生成用户可访问的路由表。</li>
<li>动态挂载路由方法 router.addRoutes。</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前端初始化路由</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">Router</span>(&#123;</span><br><span class="line">  <span class="attr">routes</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/login&#x27;</span>,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;login&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@//components/login&#x27;</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;404&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">&#x27;@//components/404&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 后端返回的路由数据 addRouter</span></span><br><span class="line">[</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;home&quot;</span>,</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">    <span class="attr">component</span>: <span class="string">&quot;home&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;home&quot;</span>,</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&quot;/userinfo&quot;</span>,</span><br><span class="line">    <span class="attr">component</span>: <span class="string">&quot;userInfo&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="comment">// vuex 添加路由表</span></span><br><span class="line"><span class="keyword">const</span> mutations = &#123;</span><br><span class="line">  [<span class="variable constant_">ADD_ROUTES</span>](state, addrouter) &#123;</span><br><span class="line">    <span class="keyword">let</span> routes = []</span><br><span class="line">    <span class="title function_">generaRouter</span>(routes, addRouter)</span><br><span class="line">    router.<span class="title function_">addRoutes</span>(routes)  </span><br><span class="line">    router.<span class="title function_">push</span>(<span class="string">&#x27;/&#x27;</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> actions = &#123;</span><br><span class="line">  <span class="title function_">add_Routes</span>(<span class="params">&#123;commit&#125;, addrouter</span>) &#123;</span><br><span class="line">    <span class="title function_">commit</span>(<span class="variable constant_">ADD_ROUTES</span>, addrouter)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">generaRouter</span>(<span class="params">routers, data</span>)&#123;</span><br><span class="line">  data.<span class="title function_">forEach</span>(<span class="function">(<span class="params">item</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> menu = <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;, item)</span><br><span class="line">    menu.<span class="property">component</span> = <span class="function">() =&gt;</span> <span class="title function_">import</span>(<span class="string">`@/components/<span class="subst">$&#123;menu.component&#125;</span>.vue`</span>)</span><br><span class="line">    <span class="keyword">if</span>(item.<span class="property">children</span>)&#123;</span><br><span class="line">        menu.<span class="property">children</span> = []</span><br><span class="line">        <span class="title function_">generaRouter</span>(menu.<span class="property">children</span>,item.<span class="property">children</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    routers.<span class="title function_">push</span>(menu)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// main.js 用户手动刷新页面时重新新增路由</span></span><br><span class="line"><span class="keyword">if</span> (sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;user&#x27;</span>)) &#123;</span><br><span class="line">    <span class="keyword">let</span> routes = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;routes&#x27;</span>))</span><br><span class="line">    store.<span class="title function_">dispatch</span>(<span class="string">&quot;add_Routes&quot;</span>, routes)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="二、数据加密"><a href="#二、数据加密" class="headerlink" title="二、数据加密"></a>二、数据加密</h1><h2 id="安全需求"><a href="#安全需求" class="headerlink" title="安全需求"></a>安全需求</h2><blockquote>
<p>前后端的传输通过 HTTP 进行传输，也带来了一些安全问题，如果抓包、模拟请求、洪水攻击、参数劫持、网络爬虫等都能够获取请求的数据包。所以项目可能需要在 http 请求中添加安全级别，常用方式如下：</p>
</blockquote>
<ul>
<li>采用 HTTPS 协议。<ul>
<li>普通的 HTTP 协议是以明文形式进行传输，不提供任何方式的数据加密，很容易解读传输报文。</li>
<li>HTTPS 协议在 HTTP 基础上加入了 SSL 层，而 SSL 层通过证书来验证服务器身份，并为浏览器和服务器之间的通信加密，保护了传输过程中的数据安全。</li>
</ul>
</li>
<li>对请求参数进行合法性校验。</li>
<li>对请求参数进行签名认证，防止参数被篡改。</li>
<li>请求隐私接口，利用 token 机制校验其合法性。</li>
<li>密钥存储到服务端而非客户端，客户端应从服务端动态获取密钥。</li>
<li>对输入输出参数进行加密，客户端加密输入参数，服务端加密输出参数。</li>
</ul>
<h2 id="加密算法"><a href="#加密算法" class="headerlink" title="加密算法"></a>加密算法</h2><ul>
<li><strong>对称加密算法</strong>：加密与解密密钥相同，主要可分为序列算法（对明文的一个单位运算）、分组算法（对明文的一组运算）。<ul>
<li><code>DES</code>：一种分组密码，以 64 位为分组对数据加密，密钥长度是 56 位。</li>
<li><code>3DES</code>：基于 DES 的对称算法，对一块数据用三个不同密钥加密三次，强度更高。</li>
<li><code>AES</code>：密码学中的高级加密标准，它采用对称分组密码体制，密钥长度的最少支持为 128、192、256 ，分组长度 128 位，算法应易于各种硬件和软件实现。</li>
</ul>
</li>
<li><strong>非对称算法</strong>：加密密钥与解密密钥不同。<ul>
<li><code>RSA</code>：目前最有影响力的公钥加密算法，可用于签名和加密。</li>
<li><code>DSA</code>：基于整数有限域离散对数难题，主要特点是两个素数公开，只用于签名。</li>
</ul>
</li>
<li><strong>散列算法</strong><ul>
<li><code>MD5</code>：单向加密的消息摘要算法(不可解密)，常用于密码认证、登陆认证。</li>
<li><code>SHA1</code>：一种比 MD5 安全性强的消息摘要算法，主要用于标准的数字签名算法。</li>
</ul>
</li>
<li><strong>其它</strong>：不需要密钥。<ul>
<li><code>Base64</code>：并非真正的加密算法，是一种用于传输 8bit 字节代码的数据编码方式，可用于 http 传递较长的标识信息。</li>
</ul>
</li>
</ul>
<h2 id="AES-加密"><a href="#AES-加密" class="headerlink" title="AES 加密"></a>AES 加密</h2><blockquote>
<p>密钥是用来加密明文的密码，不可以直接在网络上传输。加密参数和实现流程主要如下：</p>
</blockquote>
<ul>
<li><code>key length</code>：密钥位数、密码长度。</li>
<li><code>key</code>：密钥、密码。</li>
<li><code>IV</code>：初始向量（密钥偏移量），加密和解密需要相同值。</li>
<li><code>mode</code>：加密模式，分为 ECB、CBC、CFB 等，只有 ECB 没有 IV 会不太安全。</li>
<li><code>padding</code>：填充方式，分为 PKCS5、PKCS7、NOPADDING，加解密需要相同模式。</li>
</ul>
  <div align="center">
      <img src="" data-original="/images/frame/crypto.png" alt="AES 加密" width="100%">
  </div>


<h2 id="vue-加密"><a href="#vue-加密" class="headerlink" title="vue 加密"></a>vue 加密</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tool.js：封装加密算法，注意安装插件 npm i crypto-js -D</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 随机整数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">random</span>(<span class="params">min, max</span>)&#123;</span><br><span class="line">   <span class="keyword">if</span>(max == <span class="literal">null</span>)&#123;</span><br><span class="line">        max = min;  </span><br><span class="line">        min = <span class="number">0</span>;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">return</span> min + <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>()*(max-min+<span class="number">1</span>))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">** randomWord 产生任意长度随机字母数字组合</span></span><br><span class="line"><span class="comment">** randomFlag-是否任意长度 min-任意长度最小位[固定位数] max-任意长度最大位</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">randomWord</span>(<span class="params">randomFlag, min, max</span>)&#123;</span><br><span class="line">    <span class="keyword">var</span> str = <span class="string">&quot;&quot;</span>,</span><br><span class="line">    range = min,</span><br><span class="line">    arr = [<span class="string">&#x27;0&#x27;</span>, <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;4&#x27;</span>, <span class="string">&#x27;5&#x27;</span>, <span class="string">&#x27;6&#x27;</span>, <span class="string">&#x27;7&#x27;</span>, <span class="string">&#x27;8&#x27;</span>, <span class="string">&#x27;9&#x27;</span>, <span class="string">&#x27;a&#x27;</span>, <span class="string">&#x27;b&#x27;</span>, <span class="string">&#x27;c&#x27;</span>, </span><br><span class="line">    <span class="string">&#x27;d&#x27;</span>, <span class="string">&#x27;e&#x27;</span>, <span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;g&#x27;</span>, <span class="string">&#x27;h&#x27;</span>, <span class="string">&#x27;i&#x27;</span>, <span class="string">&#x27;j&#x27;</span>, <span class="string">&#x27;k&#x27;</span>, <span class="string">&#x27;l&#x27;</span>, <span class="string">&#x27;m&#x27;</span>, <span class="string">&#x27;n&#x27;</span>, <span class="string">&#x27;o&#x27;</span>, <span class="string">&#x27;p&#x27;</span>, <span class="string">&#x27;q&#x27;</span>, </span><br><span class="line">    <span class="string">&#x27;r&#x27;</span>, <span class="string">&#x27;s&#x27;</span>, <span class="string">&#x27;t&#x27;</span>, <span class="string">&#x27;u&#x27;</span>, <span class="string">&#x27;v&#x27;</span>, <span class="string">&#x27;w&#x27;</span>, <span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>, <span class="string">&#x27;z&#x27;</span>, <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;E&#x27;</span>, </span><br><span class="line">    <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;G&#x27;</span>, <span class="string">&#x27;H&#x27;</span>, <span class="string">&#x27;I&#x27;</span>, <span class="string">&#x27;J&#x27;</span>, <span class="string">&#x27;K&#x27;</span>, <span class="string">&#x27;L&#x27;</span>, <span class="string">&#x27;M&#x27;</span>, <span class="string">&#x27;N&#x27;</span>, <span class="string">&#x27;O&#x27;</span>, <span class="string">&#x27;P&#x27;</span>, <span class="string">&#x27;Q&#x27;</span>, <span class="string">&#x27;R&#x27;</span>, <span class="string">&#x27;S&#x27;</span>, </span><br><span class="line">    <span class="string">&#x27;T&#x27;</span>, <span class="string">&#x27;U&#x27;</span>, <span class="string">&#x27;V&#x27;</span>, <span class="string">&#x27;W&#x27;</span>, <span class="string">&#x27;X&#x27;</span>, <span class="string">&#x27;Y&#x27;</span>, <span class="string">&#x27;Z&#x27;</span>];</span><br><span class="line">    <span class="comment">// 随机产生</span></span><br><span class="line">    <span class="keyword">if</span>(randomFlag)&#123;</span><br><span class="line">        range = <span class="title class_">Math</span>.<span class="title function_">round</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * (max-min)) + min;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>; i &lt; range; i++)&#123;</span><br><span class="line">        pos = <span class="title class_">Math</span>.<span class="title function_">round</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * (arr.<span class="property">length</span>-<span class="number">1</span>));</span><br><span class="line">        str += arr[pos];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> str;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* crypto-js</span></span><br><span class="line"><span class="comment">* word：待加密或者解密的字符串</span></span><br><span class="line"><span class="comment">* keyStr：AES 加密需要用到的16位字符串的key</span></span><br><span class="line"><span class="comment">* @author: shichuang</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">CryptoJS</span> <span class="keyword">from</span> <span class="string">&#x27;crypto-js&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 加密</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">encrypt</span>(<span class="params">data, key, iv</span>)&#123;</span><br><span class="line">    key  = <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(key);</span><br><span class="line">    <span class="comment">// iv = CryptoJS.enc.Utf8.parse(iv);</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> encrypted = <span class="title class_">CryptoJS</span>.<span class="property">AES</span>.<span class="title function_">encrypt</span>(data, key, &#123;</span><br><span class="line">          <span class="comment">// iv, mode: CryptoJS.mode.CBC</span></span><br><span class="line">          <span class="attr">mode</span>: <span class="title class_">CryptoJS</span>.<span class="property">mode</span>.<span class="property">ECB</span>, </span><br><span class="line">          <span class="attr">padding</span>: <span class="title class_">CryptoJS</span>.<span class="property">pad</span>.<span class="property">Pkcs7</span></span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> encrypted.<span class="title function_">toString</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 解密</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">decrypt</span>(<span class="params">data, key, iv</span>)&#123;</span><br><span class="line">    key  = <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(key);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> decrypt = <span class="title class_">CryptoJS</span>.<span class="property">AES</span>.<span class="title function_">decrypt</span>(data, key, &#123;</span><br><span class="line">          <span class="comment">// iv, mode: CryptoJS.mode.CBC</span></span><br><span class="line">          <span class="attr">mode</span>: <span class="title class_">CryptoJS</span>.<span class="property">mode</span>.<span class="property">ECB</span>,</span><br><span class="line">          <span class="attr">padding</span>: <span class="title class_">CryptoJS</span>.<span class="property">pad</span>.<span class="property">Pkcs7</span></span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">stringify</span>(decrypt).<span class="title function_">toString</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// AES 对称秘钥加密</span></span><br><span class="line"><span class="keyword">const</span> aes = &#123;</span><br><span class="line">    <span class="attr">en</span>: <span class="function">(<span class="params">data</span>) =&gt;</span> <span class="title function_">getAesString</span>(data, <span class="variable constant_">KP</span>.<span class="property">key</span>),</span><br><span class="line">    <span class="attr">de</span>: <span class="function">(<span class="params">data</span>) =&gt;</span> <span class="title function_">getDAesString</span>(data, <span class="variable constant_">KP</span>.<span class="property">key</span>)</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// BASE64</span></span><br><span class="line"><span class="keyword">const</span> base64 = &#123;</span><br><span class="line">    <span class="attr">en</span>: <span class="function">(<span class="params">data</span>) =&gt;</span> <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Base64</span>.<span class="title function_">stringify</span>(<span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>.<span class="title function_">parse</span>(data)),</span><br><span class="line">    <span class="attr">de</span>: <span class="function">(<span class="params">data</span>) =&gt;</span> <span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Base64</span>.<span class="title function_">parse</span>(data).<span class="title function_">toString</span>(<span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Utf8</span>)</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// SHA256</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sha256</span> = (<span class="params">data</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">CryptoJS</span>.<span class="title class_">SHA256</span>(data).<span class="title function_">toString</span>();</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// MD5</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">md5</span> = (<span class="params">data</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">CryptoJS</span>.<span class="title class_">MD5</span>(data).<span class="title function_">toString</span>();</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 签名</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> token 身份令牌：store.state.token</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> timestamp 签名时间戳：new Date().getTime()</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> data 签名数据</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sign</span> = (<span class="params">token, timestamp, data</span>) =&gt; &#123;</span><br><span class="line">    <span class="comment">// 签名格式： timestamp + token + data (字典升序)</span></span><br><span class="line">    <span class="keyword">let</span> ret = [];</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> it <span class="keyword">in</span> data) &#123;</span><br><span class="line">        <span class="keyword">let</span> val = data[it];</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> val === <span class="string">&#x27;object&#x27;</span> &amp;&amp; (!(val <span class="keyword">instanceof</span> <span class="title class_">Array</span>) || </span><br><span class="line">        (val.<span class="property">length</span> &gt; <span class="number">0</span> &amp;&amp; (<span class="keyword">typeof</span> val[<span class="number">0</span>] === <span class="string">&#x27;object&#x27;</span>)))) &#123;</span><br><span class="line">            val = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(val);</span><br><span class="line">        &#125;</span><br><span class="line">        ret.<span class="title function_">push</span>(it + val);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 字典升序</span></span><br><span class="line">    ret.<span class="title function_">sort</span>();</span><br><span class="line">    <span class="keyword">let</span> signsrc = timestamp + token + ret.<span class="title function_">join</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">md5</span>(signsrc);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> &#123;</span><br><span class="line">    aes,</span><br><span class="line">    md5,</span><br><span class="line">    sha256,</span><br><span class="line">    base64,</span><br><span class="line">    sign</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// axios.js：数据加解密</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;@/router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">&#x27;./vuex&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123;random, randomWord, aes&#125; <span class="keyword">from</span> <span class="string">&quot;./tool.js&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ajax = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">    <span class="attr">baseURL</span>: process.<span class="property">env</span>.<span class="property">VUE_APP_URL</span>,   <span class="comment">// url 前缀</span></span><br><span class="line">    <span class="attr">timeout</span>: <span class="number">10000</span>,                     <span class="comment">// 超时毫秒数</span></span><br><span class="line">    <span class="attr">withCredentials</span>: <span class="literal">true</span>               <span class="comment">// 携带认证信息 cookie</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 请求拦截器</span></span><br><span class="line">service.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(</span><br><span class="line">    <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="variable constant_">KP</span> = &#123;</span><br><span class="line">            <span class="attr">key</span>: <span class="title function_">randomWord</span>(<span class="literal">true</span>, <span class="number">16</span>, <span class="number">20</span>),  <span class="comment">// 秘钥</span></span><br><span class="line">            <span class="attr">iv</span>: <span class="title function_">randomWord</span>(<span class="literal">true</span>, <span class="number">16</span>, <span class="number">20</span>)    <span class="comment">// 偏移量</span></span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="comment">// 加密</span></span><br><span class="line">        config.<span class="property">data</span> = aes.<span class="title function_">en</span>(config.<span class="property">data</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 设置表头  &#x27;application/json&#x27;</span></span><br><span class="line">        config.<span class="property">headers</span> = &#123;</span><br><span class="line">            <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/json;charset=utf-8&quot;</span>,</span><br><span class="line">            <span class="attr">url</span>: config.<span class="property">url</span>,</span><br><span class="line">            <span class="attr">method</span>: config.<span class="property">method</span>,</span><br><span class="line">            <span class="attr">shareKey</span>: <span class="variable constant_">KP</span>.<span class="property">key</span>,</span><br><span class="line">            <span class="attr">shareIv</span>: <span class="variable constant_">KP</span>.<span class="property">iv</span>,</span><br><span class="line">            <span class="attr">timestamp</span>: <span class="keyword">new</span> <span class="title class_">Date</span>().<span class="title function_">getTime</span>(),  <span class="comment">// 时间戳</span></span><br><span class="line">            <span class="attr">token</span>: store.<span class="property">state</span>.<span class="property">token</span>,</span><br><span class="line">            <span class="attr">requestStr</span>: <span class="title function_">random</span>(<span class="number">100</span>, <span class="number">1</span>)</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> config</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">    &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> url 请求 url</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> method get、post</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> params 参数</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> level 0：无加密，1：参数加密，2：签名+时间戳，默认0</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">_request</span> (url, methods, data = <span class="literal">undefined</span>, params = &#123;&#125;, level = <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">service</span>(&#123;</span><br><span class="line">            <span class="attr">method</span>: methods,</span><br><span class="line">            <span class="attr">url</span>: url,</span><br><span class="line">            <span class="attr">data</span>: data,</span><br><span class="line">            <span class="attr">params</span>: <span class="title class_">Object</span>.<span class="title function_">assign</span>(params),</span><br><span class="line">            <span class="attr">headers</span>: &#123; level &#125;</span><br><span class="line">            </span><br><span class="line">        &#125;).<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">resolve</span>(response.<span class="property">data</span>)</span><br><span class="line">        &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">reject</span>(error)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="三、数据更新"><a href="#三、数据更新" class="headerlink" title="三、数据更新"></a>三、数据更新</h1><h2 id="重置组件数据"><a href="#重置组件数据" class="headerlink" title="重置组件数据"></a>重置组件数据</h2><blockquote>
<p>this.$data 当前状态下的数据、this.$options.data() 该组件初始状态下的数据。</p>
</blockquote>
<ul>
<li>表单：<code>this.form = this.$options.data().form</code></li>
<li>组件：<code>Object.assign(this.$data, this.$options.data())</code></li>
</ul>
<h2 id="更新路由数据"><a href="#更新路由数据" class="headerlink" title="更新路由数据"></a>更新路由数据</h2><blockquote>
<p>路由变化后页面数据并未更新，原因是跳转前后使用同一个组件，vue-router 默认复用组件而没有执行 created 等生命周期钩子。</p>
</blockquote>
<ul>
<li>普通方案：监听 $route 变化来初始化数据 <code>watch: &#123; &#39;$route&#39;: &#123;handler: &#39;resetData&#39;,immediate: true&#125; &#125;</code>。</li>
<li>简单方案：监听路由地址变化来重新创建组件 <code>&lt;router-view :key=&quot;$route.fullPath&quot;&gt;&lt;/router-view&gt;</code>。</li>
</ul>
<h2 id="页面刷新方法"><a href="#页面刷新方法" class="headerlink" title="页面刷新方法"></a>页面刷新方法</h2><ul>
<li><code>router.go(0)</code>：兼容性不好</li>
<li><code>window.location.reload()</code>：会清空 vuex 数据</li>
<li><code>provice + inject</code>：推荐使用</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 根组件定义：router-view v-if=&quot;isRouterAlive&quot;\</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span><br><span class="line">    provide ()&#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">reload</span>: <span class="variable language_">this</span>.<span class="property">reload</span> &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">data</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">isRouterAlive</span>: <span class="literal">true</span>  &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">methods</span>:&#123;</span><br><span class="line">        reload () &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">isRouterAlive</span> = <span class="literal">false</span></span><br><span class="line">            <span class="variable language_">this</span>.$nextTick(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">                <span class="variable language_">this</span>.<span class="property">isRouterAlive</span> = <span class="literal">true</span></span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子组件引用</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="attr">inject</span>: [<span class="string">&#x27;reload&#x27;</span>],</span><br><span class="line">    <span class="attr">method</span>: &#123;</span><br><span class="line">        <span class="title function_">fn</span>(<span class="params"></span>)&#123; <span class="variable language_">this</span>.<span class="title function_">reload</span>() &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="数据更新问题"><a href="#数据更新问题" class="headerlink" title="数据更新问题"></a>数据更新问题</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 刷新网页后 vuex 数据丢失的解决方案  </span></span><br><span class="line"><span class="title function_">created</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">if</span> (sessionStorage.<span class="title function_">getItem</span>(<span class="string">&quot;store&quot;</span>) ) &#123;</span><br><span class="line">        <span class="keyword">let</span> storeData = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&quot;store&quot;</span>))</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="title function_">replaceState</span>(<span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;, <span class="variable language_">this</span>.<span class="property">$store</span>.<span class="property">state</span>, storeData))</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;beforeunload&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        sessionStorage.<span class="title function_">setItem</span>(<span class="string">&quot;store&quot;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(<span class="variable language_">this</span>.<span class="property">$store</span>.<span class="property">state</span>))</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 更新对象或数组后对应的视图值却不刷新</span></span><br><span class="line">更新对象：<span class="variable language_">this</span>.$set(obj, key, value)</span><br><span class="line">更新数组：<span class="variable language_">this</span>.$set(arr, index, value)</span><br></pre></td></tr></table></figure>


<h1 id="四、页面缓存"><a href="#四、页面缓存" class="headerlink" title="四、页面缓存"></a>四、页面缓存</h1><h2 id="组件缓存"><a href="#组件缓存" class="headerlink" title="组件缓存"></a>组件缓存</h2><blockquote>
<p>缓存组件只会在首次进入时执行一次生命周期钩子，再次进入则从缓存中获取数据等。</p>
</blockquote>
  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">全部缓存</span><br><span class="line"><span class="tag">&lt;<span class="name">keep-alive</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span><span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"></span><br><span class="line">部分缓存</span><br><span class="line"><span class="tag">&lt;<span class="name">keep-alive</span> <span class="attr">include</span>=<span class="string">&quot;a, b&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">router-view</span>/&gt;</span><span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">keep-alive</span> <span class="attr">exclude</span>=<span class="string">&quot;a, b&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"></span><br><span class="line">export default new Router([</span><br><span class="line">    &#123;</span><br><span class="line">        path: &#x27;/&#x27;,</span><br><span class="line">        name: &#x27;home&#x27;,</span><br><span class="line">        component: Home,</span><br><span class="line">        meta: &#123;</span><br><span class="line">            keepAlive: true   // 需要被缓存</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;<span class="name">keep-alive</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">router-view</span> <span class="attr">v-if</span>=<span class="string">&quot;$route.meta.keepAlive&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">keep-alive</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">router-view</span> <span class="attr">v-if</span>=<span class="string">&quot;!$route.meta.keepAlive&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">router-view</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="旧版本缓存"><a href="#旧版本缓存" class="headerlink" title="旧版本缓存"></a>旧版本缓存</h2><blockquote>
<p>浏览器缓存会导致 vue 打包的文件偶尔会出现不能更新最新的打包代码，因此在打包的文件名中添加一个版本号以便浏览器能区分。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// vue.config.js：解决 js 缓存问题</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Timestamp</span> = <span class="keyword">new</span> <span class="title class_">Date</span>().<span class="title function_">getTime</span>();</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">configureWebpack</span>: &#123;    <span class="comment">// webpack 配置</span></span><br><span class="line">    <span class="attr">output</span>: &#123;            <span class="comment">// 输出重构，打包编译后的文件名称：模块名称.版本号.时间戳</span></span><br><span class="line">      <span class="attr">filename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span>,</span><br><span class="line">      <span class="attr">chunkFilename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span></span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 其他写法</span></span><br><span class="line">  <span class="attr">configureWebpack</span>: <span class="function">(<span class="params">config</span>) =&gt;</span> &#123; </span><br><span class="line">    <span class="title class_">Object</span>.<span class="title function_">assign</span>(config, &#123;</span><br><span class="line">      <span class="comment">// 开发生产共同配置</span></span><br><span class="line">      <span class="attr">output</span>: &#123;            <span class="comment">// 输出重构，打包编译后的文件名称：模块名称.版本号.时间戳</span></span><br><span class="line">        <span class="attr">filename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span>,</span><br><span class="line">        <span class="attr">chunkFilename</span>: <span class="string">`[name]-<span class="subst">$&#123;process.env.VUE_APP_Version&#125;</span>-<span class="subst">$&#123;Timestamp&#125;</span>.js`</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="comment">// 别名配置</span></span><br><span class="line">      <span class="attr">resolve</span>: &#123;</span><br><span class="line">        <span class="attr">alias</span>: &#123;</span><br><span class="line">          <span class="string">&#x27;@&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;@c&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src/components&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;@p&#x27;</span>: path.<span class="title function_">resolve</span>(**dirname, <span class="string">&#x27;./src/pages&#x27;</span>)</span><br><span class="line">        &#125; </span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desp</span> nginx 配置：不缓存 index.html </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desp</span> <span class="variable">no</span>-cache、no-store 可以只设置一个 </span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * no-cache：浏览器会缓存，但刷新页面或者重新打开时会请求服务器</span></span><br><span class="line"><span class="comment"> * no-store：浏览器不缓存，刷新页面需要重新下载页面</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line">location = /index.<span class="property">html</span> &#123;</span><br><span class="line">  add_header <span class="title class_">Cache</span>-<span class="title class_">Control</span> <span class="string">&quot;no-cache, no-store&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="五、组件库优化"><a href="#五、组件库优化" class="headerlink" title="五、组件库优化"></a>五、组件库优化</h1><blockquote>
<p>elementui、antd 等组件库的组件经常满足不了项目的个性化需求，Vue Demo Collection 项目收集了一些通用的 Vue 组件，有需要时可查看。</p>
</blockquote>
<h2 id="组件样式"><a href="#组件样式" class="headerlink" title="组件样式"></a>组件样式</h2>  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 全局修改：代码覆盖、根据官网自定义主题的教程修改</span></span><br><span class="line"><span class="keyword">@import</span> <span class="string">&quot;./assets/css/index.css&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改单个文件的样式时，可以使用 /deep/、&gt;&gt;&gt; 来深度选择。</span></span><br><span class="line"><span class="selector-class">.dialog-wrapper</span> &#123;</span><br><span class="line">    /deep/<span class="selector-class">.el-dialog</span>**<span class="selector-tag">body</span>&#123;</span><br><span class="line">        <span class="attribute">border</span>: solid <span class="number">1px</span> <span class="number">#999</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="组件参数和方法"><a href="#组件参数和方法" class="headerlink" title="组件参数和方法"></a>组件参数和方法</h2>  <figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">我想要在 el-cascader 选中一个搜索选项后不关闭看板，通过源码发现 toggleDropDownVisible</span><br><span class="line">方法是控制看板展开的，所以通过 ref 获取组件并调用其方法。</span><br><span class="line"><span class="tag">&lt;<span class="name">el-cascader</span></span></span><br><span class="line"><span class="tag">    <span class="attr">ref</span>=<span class="string">&quot;cascader&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">placeholder</span>=<span class="string">&quot;试试搜索：指南&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">:options</span>=<span class="string">&quot;options&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">:props</span>=<span class="string">&quot;&#123; multiple: true &#125;&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">filterable</span>&gt;</span>&lt;/el-cascader</span><br><span class="line">    @visible-change=&quot;$refs.cascader.toggleDropDownVisible(true)&quot;&gt;</span><br><span class="line"><span class="tag">&lt;/<span class="name">el-cascader</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="组件功能扩展"><a href="#组件功能扩展" class="headerlink" title="组件功能扩展"></a>组件功能扩展</h2><blockquote>
<p>element-ui 多选可搜索级联组件有一个问题：当用户选中全部子节点时不会合并为显示父节点，于是可进行以下优化：</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 默认看到级联看板展开，不会收起</span></span><br><span class="line">@visible-change=<span class="string">&quot;blurCascader(true)&quot;</span> <span class="comment">// 可触发展开</span></span><br><span class="line">mounted () &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">blurCascader</span>(<span class="literal">true</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 失焦后触发展开级联看板（默认失焦后关闭看板）</span></span><br><span class="line">blurCascader () &#123;</span><br><span class="line">    <span class="variable language_">this</span>.$nextTick(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 调用组件内部未暴露的方法</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">cascader</span>.<span class="title function_">toggleDropDownVisible</span>(<span class="literal">true</span>) </span><br><span class="line">    &#125;)</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 搜索选中后展示级联看板，并勾选搜索选中的节点</span></span><br><span class="line"><span class="comment">// 响应选中的节点，选中节点后关闭选择看板，展示级联看板</span></span><br><span class="line">changecascader (e) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">cascader</span>.<span class="title function_">handleDropdownLeave</span>()</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"><span class="comment">// 当子级节点全部选中后，tag只展示一个父级节点，而不是全部子节点。</span></span><br><span class="line"><span class="title function_">getPresetTags</span>(<span class="params"></span>) &#123;   <span class="comment">// 获取所有勾选的节点</span></span><br><span class="line">    <span class="keyword">const</span> tree = <span class="variable language_">this</span>.<span class="property">panel</span>.<span class="property">menus</span>[<span class="number">0</span>]</span><br><span class="line">    <span class="keyword">const</span> result = []</span><br><span class="line">    <span class="title function_">loop</span>(tree)</span><br><span class="line">    <span class="comment">// 递归查找选中的节点</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">loop</span>(<span class="params">tree = []</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; tree.<span class="property">length</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> child = tree[i]</span><br><span class="line">            <span class="comment">// checked 状态表示选中、indeterminate 状态表示待定，是半选</span></span><br><span class="line">            <span class="keyword">if</span> (child.<span class="property">checked</span>) &#123;                </span><br><span class="line">                result.<span class="title function_">push</span>(&#123; ...child, <span class="attr">closable</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (child.<span class="property">indeterminate</span>) &#123;</span><br><span class="line">                child.<span class="property">children</span> &amp;&amp; <span class="title function_">loop</span>(child.<span class="property">children</span>)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">presentFormatTags</span> = result <span class="comment">// 得到可显示的 tag</span></span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"><span class="comment">// 删除节点：由于修改了 tag 展示，所以它的 deleteTag 事件也要重写。</span></span><br><span class="line"><span class="title function_">deleteTag</span>(<span class="params">index, tag</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> _ = <span class="variable language_">this</span></span><br><span class="line">    <span class="keyword">if</span> (tag &amp;&amp; tag.<span class="property">hasChildren</span>) &#123;</span><br><span class="line">        <span class="comment">// 当删除的节点是父节点时</span></span><br><span class="line">        <span class="title function_">loop</span>(tag.<span class="property">children</span>)</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">loop</span>(<span class="params">list</span>) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; list.<span class="property">length</span>; i++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (list[i].<span class="property">hasChildren</span>) &#123;</span><br><span class="line">                    <span class="title function_">loop</span>(list[i].<span class="property">children</span>)</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">let</span> path = list[i].<span class="property">path</span></span><br><span class="line">                    _.<span class="property">checkedValue</span> = _.<span class="property">checkedValue</span>.<span class="title function_">filter</span>(<span class="function"><span class="params">n</span> =&gt;</span> n !== path)</span><br><span class="line">                    _.$emit(<span class="string">&#x27;remove-tag&#x27;</span>, tag)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (tag) &#123;   <span class="comment">// 当删除的是子节点时</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">checkedValue</span> = <span class="variable language_">this</span>.<span class="property">checkedValue</span>.<span class="title function_">filter</span>(<span class="function">(<span class="params">n, i</span>) =&gt;</span> n !== tag.<span class="property">path</span>)</span><br><span class="line">        <span class="variable language_">this</span>.$emit(<span class="string">&#x27;remove-tag&#x27;</span>, tag)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;  <span class="comment">// 当以回车键删除时</span></span><br><span class="line">        <span class="keyword">const</span> temp = <span class="variable language_">this</span>.<span class="property">presentFormatTags</span>[<span class="variable language_">this</span>.<span class="property">presentFormatTags</span>.<span class="property">length</span> - <span class="number">1</span>]</span><br><span class="line">        temp &amp;&amp; <span class="variable language_">this</span>.<span class="title function_">deleteTag</span>(<span class="literal">null</span>, temp)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 原本这个方法的代码如下</span></span><br><span class="line">    <span class="comment">// const &#123; checkedValue &#125; = this</span></span><br><span class="line">    <span class="comment">// const val = checkedValue[index]</span></span><br><span class="line">    <span class="comment">// this.checkedValue = checkedValue.filter((n, i) =&gt; i !== index)</span></span><br><span class="line">    <span class="comment">// this.$emit(&#x27;remove-tag&#x27;, val)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="多个组件联动"><a href="#多个组件联动" class="headerlink" title="多个组件联动"></a>多个组件联动</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 将 table、pagination 放到一个组件</span></span><br><span class="line">&lt;template lang=<span class="string">&quot;pug&quot;</span>&gt;</span><br><span class="line">div</span><br><span class="line">  .<span class="property">el</span>-table</span><br><span class="line">    <span class="title function_">template</span>(v-<span class="keyword">for</span>=<span class="string">&quot;(item, index) in columns&quot;</span>)</span><br><span class="line">      el-table-<span class="title function_">column</span>(</span><br><span class="line">        :prop=<span class="string">&quot;item.prop&quot;</span></span><br><span class="line">        :key=<span class="string">&quot;index&quot;</span></span><br><span class="line">        :label=<span class="string">&quot;item.label&quot;</span>)</span><br><span class="line"></span><br><span class="line">  el-pagination.<span class="property">pg</span>-<span class="title function_">wrapper</span>(</span><br><span class="line">    layout=<span class="string">&quot;total, sizes, prev, pager, next, jumper&quot;</span></span><br><span class="line">    @size-change=<span class="string">&quot;handleSizeChange&quot;</span></span><br><span class="line">    @current-change=<span class="string">&quot;handleCurrentChange&quot;</span></span><br><span class="line">    :current-page=<span class="string">&quot;currentPage&quot;</span></span><br><span class="line">    :page-sizes=<span class="string">&quot;[10, 20, 50, 100]&quot;</span></span><br><span class="line">    :page-size=<span class="string">&quot;pagesize&quot;</span></span><br><span class="line">    :total=<span class="string">&quot;total&quot;</span>)</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 传入参数</span></span><br><span class="line"><span class="attr">props</span>: &#123;</span><br><span class="line">    <span class="comment">// 列信息</span></span><br><span class="line">    <span class="attr">columns</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Array</span>,</span><br><span class="line">      <span class="attr">default</span>: [],</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 单页数据量</span></span><br><span class="line">    <span class="attr">pagesize</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Number</span>,</span><br><span class="line">      <span class="attr">default</span>: <span class="number">10</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 当前页码</span></span><br><span class="line">    <span class="attr">currentPage</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Number</span>,</span><br><span class="line">      <span class="attr">default</span>: <span class="number">1</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 表格数据</span></span><br><span class="line">    <span class="attr">tableData</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Array</span>,</span><br><span class="line">      <span class="attr">default</span>: [],</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 数据总数</span></span><br><span class="line">    <span class="attr">total</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Number</span>,</span><br><span class="line">      <span class="attr">default</span>: <span class="number">1000</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 获取数据的接口</span></span><br><span class="line">    <span class="attr">fetch</span>:&#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="keyword">function</span>,</span><br><span class="line">      <span class="attr">default</span>:<span class="function">() =&gt;</span> &#123;&#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 表单查询的参数</span></span><br><span class="line">    <span class="attr">query</span>:&#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">Object</span>,</span><br><span class="line">      <span class="attr">default</span>: <span class="function">() =&gt;</span> &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;,</span><br><span class="line"><span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="comment">// 改变当前页码 currentPage 时触发</span></span><br><span class="line">    <span class="attr">handleCurrentChange</span>: <span class="keyword">function</span> (<span class="params">currentPage</span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&#x27;handleChange&#x27;</span>, <span class="variable language_">this</span>.<span class="property">pagesize</span>, currentPage)</span><br><span class="line">      <span class="variable language_">this</span>.<span class="title function_">fetch</span>(<span class="variable language_">this</span>.<span class="property">query</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 改变当前页 pageSize 时触发</span></span><br><span class="line">    <span class="attr">handleSizeChange</span>: <span class="keyword">function</span> (<span class="params">pageSize</span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&#x27;handleChange&#x27;</span>, pageSize, <span class="variable language_">this</span>.<span class="property">currentPage</span>)</span><br><span class="line">      <span class="variable language_">this</span>.<span class="title function_">fetch</span>(<span class="variable language_">this</span>.<span class="property">query</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>






    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/06/10/5-2-vue%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF/" title="Vue 常见场景的解决方案">https://chuangges.gitee.io/2019/06/10/5-2-vue常见场景/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/06/05/5-1-vue%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/" rel="prev" title="Vue 项目构建">
      <i class="fa fa-chevron-left"></i> Vue 项目构建
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/06/16/7-1-Node%E5%9F%BA%E7%A1%80/" rel="next" title="Node.js 主要内容">
      Node.js 主要内容 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E8%B7%AF%E7%94%B1%E6%8E%A7%E5%88%B6"><span class="nav-number">1.</span> <span class="nav-text">一、路由控制</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%99%BB%E5%BD%95%E9%AA%8C%E8%AF%81"><span class="nav-number">1.1.</span> <span class="nav-text">登录验证</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9D%83%E9%99%90%E6%8E%A7%E5%88%B6"><span class="nav-number">1.2.</span> <span class="nav-text">权限控制</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81%E6%95%B0%E6%8D%AE%E5%8A%A0%E5%AF%86"><span class="nav-number">2.</span> <span class="nav-text">二、数据加密</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%89%E5%85%A8%E9%9C%80%E6%B1%82"><span class="nav-number">2.1.</span> <span class="nav-text">安全需求</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95"><span class="nav-number">2.2.</span> <span class="nav-text">加密算法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AES-%E5%8A%A0%E5%AF%86"><span class="nav-number">2.3.</span> <span class="nav-text">AES 加密</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#vue-%E5%8A%A0%E5%AF%86"><span class="nav-number">2.4.</span> <span class="nav-text">vue 加密</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0"><span class="nav-number">3.</span> <span class="nav-text">三、数据更新</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%87%8D%E7%BD%AE%E7%BB%84%E4%BB%B6%E6%95%B0%E6%8D%AE"><span class="nav-number">3.1.</span> <span class="nav-text">重置组件数据</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9B%B4%E6%96%B0%E8%B7%AF%E7%94%B1%E6%95%B0%E6%8D%AE"><span class="nav-number">3.2.</span> <span class="nav-text">更新路由数据</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%A1%B5%E9%9D%A2%E5%88%B7%E6%96%B0%E6%96%B9%E6%B3%95"><span class="nav-number">3.3.</span> <span class="nav-text">页面刷新方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E9%97%AE%E9%A2%98"><span class="nav-number">3.4.</span> <span class="nav-text">数据更新问题</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E9%A1%B5%E9%9D%A2%E7%BC%93%E5%AD%98"><span class="nav-number">4.</span> <span class="nav-text">四、页面缓存</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E7%BC%93%E5%AD%98"><span class="nav-number">4.1.</span> <span class="nav-text">组件缓存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%97%A7%E7%89%88%E6%9C%AC%E7%BC%93%E5%AD%98"><span class="nav-number">4.2.</span> <span class="nav-text">旧版本缓存</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81%E7%BB%84%E4%BB%B6%E5%BA%93%E4%BC%98%E5%8C%96"><span class="nav-number">5.</span> <span class="nav-text">五、组件库优化</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F"><span class="nav-number">5.1.</span> <span class="nav-text">组件样式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E5%8F%82%E6%95%B0%E5%92%8C%E6%96%B9%E6%B3%95"><span class="nav-number">5.2.</span> <span class="nav-text">组件参数和方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E5%8A%9F%E8%83%BD%E6%89%A9%E5%B1%95"><span class="nav-number">5.3.</span> <span class="nav-text">组件功能扩展</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%9A%E4%B8%AA%E7%BB%84%E4%BB%B6%E8%81%94%E5%8A%A8"><span class="nav-number">5.4.</span> <span class="nav-text">多个组件联动</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
